package com.dge.common.base.view

import android.app.Activity
import android.content.Intent
import android.os.Bundle
import android.view.KeyEvent
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.lifecycle.Lifecycle
import androidx.viewbinding.ViewBinding
import com.dylanc.viewbinding.base.FragmentBinding
import com.dylanc.viewbinding.base.FragmentBindingDelegate
import com.hjq.toast.ToastUtils
import com.dge.common.action.KeyboardAction
import com.dge.common.action.ToastAction
import com.dge.common.common.AppConfig
import com.dge.common.extentions.isVisibleOnScreen
import com.dge.common.utils.LoadingDialogUtils
import com.dge.common.utils.OkHttpUtils
import com.lxj.xpopup.impl.LoadingPopupView
import kotlinx.coroutines.CoroutineScope
import org.greenrobot.eventbus.EventBus
import kotlin.coroutines.CoroutineContext

//需要被继承，需要用open修饰
open class BaseFragment<T : ViewBinding> : Fragment(), MvpView, KeyboardAction, ToastAction, CoroutineScope,
    FragmentBinding<T> by FragmentBindingDelegate() {
    protected var reuseRootView = false //是否重用rootView
    private var rootView: View? = null
    val loadingDialog: LoadingPopupView?
        get() = if (activity != null) LoadingDialogUtils.dialogMap[activity?.localClassName] else null

    //协程
    override val coroutineContext: CoroutineContext
        get() = kotlinx.coroutines.Dispatchers.Main
    val isDebug: Boolean get() = AppConfig.isDebug()
    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        return if (reuseRootView) {
            if (rootView != null)
                rootView
            else {
                rootView = createViewWithBinding(inflater, container)
                rootView
            }
        } else {
            createViewWithBinding(inflater, container)
        }
    }

    override fun onDestroyView() {
        OkHttpUtils.cancelTag(this)//取消HttpUtils方式的请求
        LoadingDialogUtils.hideLoading(requireActivity(), true)
        // 销毁dialog
        if (reuseRootView) {
            if (rootView != null) {
                super.onDestroyView()
                // (rootView!!.parent as ViewGroup).removeView(rootView)
            } else {
                super.onDestroyView()
            }
        } else {
            super.onDestroyView()
        }
    }

    fun showLoading(
        msg: String? = null,
        dismissOnBackPressed: Boolean = true,
        dismissOnTouchOutside: Boolean = true,
        isLightStatusBar: Boolean = true
    ) {
        val isVisible = !isFinished() && binding.root.isVisibleOnScreen(true)
        // Timber.i("showLoading isVisible = $isVisible ${this.javaClass.simpleName}")
        if (isVisible) {
            LoadingDialogUtils.showLoading(
                requireActivity(),
                msg,
                dismissOnBackPressed,
                dismissOnTouchOutside,
                isLightStatusBar
            )
        }
    }

    override fun showLoading() {
        showLoading(null, true, true, true)
    }

    override fun showLoading(msg: String) {
        showLoading(msg, true, true, true)
    }

    override fun hideLoading() {
        if (isFinished()) return
        // val isVisible = !isFinished() && binding.root.isVisibleOnScreen(true)
        // if (isVisible) {
        LoadingDialogUtils.hideLoading(requireActivity())
        // }
    }

    fun isFinished(): Boolean {
        return !isAdded
    }

    /**
     * 跳转 Activity 简化版
     */
    open fun startActivity(clazz: Class<out Activity>) {
        startActivity(Intent(context, clazz))
    }

    /**
     * 针对startActivityForResult 方法优化
     */
    open fun startActivityForResult(clazz: Class<out Activity>, callback: BaseActivity.OnActivityCallback?) {
        if (activity != null && activity is BaseActivity<*>) {
            (activity as BaseActivity<*>).startActivityForResult(clazz, callback)
        } else {
            ToastUtils.show("宿主Activity不是BaseActivity，请不要使用该方法")
        }
    }

    open fun startActivityForResult(intent: Intent, callback: BaseActivity.OnActivityCallback?) {
        if (activity != null && activity is BaseActivity<*>) {
            (activity as BaseActivity<*>).startActivityForResult(intent, null, callback)
        } else {
            ToastUtils.show("宿主Activity不是BaseActivity，请不要使用该方法")
        }
    }

    open fun startActivityForResult(intent: Intent, options: Bundle?, callback: BaseActivity.OnActivityCallback?) {
        if (activity != null && activity is BaseActivity<*>) {
            (activity as BaseActivity<*>).startActivityForResult(intent, options, callback)
        } else {
            ToastUtils.show("宿主Activity不是BaseActivity，请不要使用该方法")
        }
    }

    /**
     * Fragment 按键事件派发
     */
    open fun dispatchKeyEvent(event: KeyEvent?): Boolean {
        val fragments: MutableList<Fragment?> = childFragmentManager.fragments
        for (fragment: Fragment? in fragments) {
            // 这个子 Fragment 必须是 BaseFragment 的子类，并且处于可见状态
            if (fragment !is BaseFragment<*> || fragment.lifecycle.currentState != Lifecycle.State.RESUMED) {
                continue
            }
            // 将按键事件派发给子 Fragment 进行处理
            if (fragment.dispatchKeyEvent(event)) {
                // 如果子 Fragment 拦截了这个事件，那么就不交给父 Fragment 处理
                return true
            }
        }
        return when (event?.action) {
            KeyEvent.ACTION_DOWN -> onKeyDown(event.keyCode, event)
            KeyEvent.ACTION_UP -> onKeyUp(event.keyCode, event)
            else -> false
        }
    }

    /**
     * 按键按下事件回调
     */
    open fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean {
        // 默认不拦截按键事件
        return false
    }

    /**
     * 按键抬起事件回调
     */
    open fun onKeyUp(keyCode: Int, event: KeyEvent?): Boolean {
        // 默认不拦截按键事件
        return false
    }

    fun registerEventBus() {
        if (!EventBus.getDefault().isRegistered(this)) {
            EventBus.getDefault().register(this)
        }
    }

    fun unregisterEventBus() {
        if (EventBus.getDefault().isRegistered(this)) {
            EventBus.getDefault().unregister(this)
        }
    }

    private fun getClassName(): String {
        return this.javaClass.simpleName
    }
}